/**
 * JAVACC DEMO 1.0
 */
package com.apache.ius.able;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.apache.api.api.ApiService;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.util.Validator;
import com.apache.client.IUSRequestParams;
import com.apache.client.StringUtil;
import com.apache.database.model.Page;
import com.apache.excp.ExcelExpUtil;
import com.apache.ius.IusSqlTools;
import com.apache.ius.plugin.IusPluginUtil;
import com.apache.tools.StrUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * description: 导出任务线程类
 *
 * @author qihan 创建时间：2020-8-28
 */
public class ExportDataTask implements Callable<Integer> {
    private Logger log = LoggerFactory.getLogger(ExportDataTask.class);

    private ParamsVo vo;
    private ApiService iusService;
    private Map<String,Object> resqData;
    private int exportPageSize =5000;

    public ExportDataTask(){

    }

    public ExportDataTask(ParamsVo vo, ApiService iusService,Map<String,Object> resqData) {
        this.vo = vo;
        this.iusService = iusService;
        this.resqData = resqData;
    }

    public void setParams(ParamsVo vo, ApiService iusService,Map<String,Object> resqData) {
        this.vo = vo;
        this.iusService = iusService;
        this.resqData = resqData;
    }

    /**
     * TODO 简单描述该方法的实现功能（可选）.
     *
     * @see Callable#call()
     */
    public Integer call() throws Exception {
        try {
            String filePath = String.valueOf(resqData.get("filePath"));
            String fileName = String.valueOf(resqData.get("fileName"));
            String fileType = String.valueOf(resqData.get("fileType"));
            log.info("filePath->"+filePath);
            log.info("fileName->"+fileName);
            boolean isxlsx = ".xlsx".equals(fileType);
            long totalRows = 0l;
            if(StrUtil.isNull(vo.getParamsToStr("exportType"))){
                totalRows=exportByPageNameFormName(filePath, fileName, isxlsx);//走IUS接口导出数据
            } else {
                Workbook workbook = null;
                if(isxlsx) {
                    workbook = ExcelExpUtil.getSXSSFWorkbook(100);
                } else {
                    workbook = ExcelExpUtil.getHSSFWorkbook();
                }
                log.info("全表数据导出，则默认取数据结果集中第1条数据的字段名称为表头。");
                String sql = "select * from "+vo.getParamsToStr("tableName");
                String datasource = vo.getParamsToStr("sysName");
                log.info("数据查询sql->"+sql);
                log.info("数据源datasource->"+datasource);
                int j = 1;
                String exportFileName = StrUtil.doNull(vo.getParamsToStr("fileName"),vo.getParamsToStr("exportFileName"));
                log.info("sheetName->"+exportFileName);
                boolean mark = true;
                do {
                    int rowNum = (j-1) * exportPageSize;
                    Page page = (Page)IusPluginUtil.getInstance().select(datasource, sql, j, exportPageSize);
                    totalRows=page.getCount();
                    if (StrUtil.isEmpty(page.getPageObjects())) {
                        log.info("查询结果无数据，暂不进行导出处理！");
                        resqData.put("ex_msg","查询结果无数据，暂不进行导出处理！");
                        mark = false;
                    } else {
                        log.info(j+").查询出数据["+page.getPageObjects().size()+"]条。");
                        if (j >= page.getPageCount()) {
                            mark = false;
                        } else {
                            j++;
                        }
                        if(rowNum>0){
                            rowNum += 1;
                        }
                        ExcelExpUtil.doInvoke(workbook, exportFileName, null, page.getPageObjects(), rowNum);
                        page = null;
                    }
                } while (mark);
                if(null != workbook){
                    ExcelExpUtil.writeXlsx(workbook, filePath, fileName);
                }
            }
            if(!resqData.containsKey("ex_msg")){
                log.info("本次共计导出数据["+totalRows+"]条。");
                log.info("文件生成完成："+filePath+"/"+fileName);
            }
        } catch (Exception e) {
            e.printStackTrace();
            resqData.put("ex_msg","发生异常："+e.getMessage());
            return 0;
        }
        return 1;
    }

    /**
     * 以PageName、fromName方式导出数据
     */
    private long exportByPageNameFormName(String filePath, String fileName, boolean isxlsx) throws Exception {
        boolean mark = true;
        long totalRows = 0l;
        int j = 1;
        vo.setParams("rows", exportPageSize);
        List<Map> cells = (List)resqData.get("data_titles");
        if(StrUtil.isEmpty(cells)){
            log.info("未配置表头，则默认取数据结果集中第1条数据的字段名称为表头。");
        }else{
            log.info("已配置表头，共记配置["+cells.size()+"]个！");
        }
        String exportFileName = StrUtil.doNull(vo.getParamsToStr("fileName"),vo.getParamsToStr("exportFileName"));
        log.info("sheetName->"+exportFileName);
        Workbook workbook = null;
        if(isxlsx) {
            workbook = ExcelExpUtil.getSXSSFWorkbook(100);
        } else {
            workbook = ExcelExpUtil.getHSSFWorkbook();
        }
        do {
            vo.setParams("_resultType", "F");
            vo.setParams("page", j);
            int rowNum = (j-1) * exportPageSize;
            ResultEntity entity = iusService.doService(vo);
            if (null == entity.getEntity()) {
                mark = false;
            } else {
                List<Map> list = new ArrayList();
                if (entity.getEntity() instanceof Page) {
                    Page page = (Page) entity.getEntity();
                    if (!Validator.isEmpty(page.getPageObjects())) {
                        list.addAll(page.getPageObjects());
                        if (j >= page.getPageCount()) {
                            mark = false;
                        } else {
                            j++;
                        }
                    } else {
                        mark = false;
                    }
                } else if(entity.getEntity() instanceof List){
                    list= (List) entity.getEntity();
                } else {
                    mark = false;
                }
                log.info(j+").查询出数据["+list.size()+"]条。");
                totalRows+=list.size();
                if(!list.isEmpty()){
                    if(rowNum>0){
                        rowNum += 1;
                    }
                    ExcelExpUtil.doInvoke(workbook, exportFileName, cells, list, rowNum);
                    list = null;
                }else{
                    log.info("查询结果无数据，暂不进行导出处理！");
                    resqData.put("ex_msg","查询结果无数据，暂不进行导出处理！");
                }
            }
        } while (mark);
        if(null != workbook){
            ExcelExpUtil.writeXlsx(workbook, filePath, fileName);
        }
        return totalRows;
    }

    /**
     * 获取接口配置的导出参数
     * @param pageName 接口pageName
     * @param fromName 接口fromName
     */
    public Map<String,Object> exportConfig(String pageName,String fromName){
        Map<String,Object> resqData = new HashMap();
        if(StrUtil.isNull(pageName) && StrUtil.isNull(fromName)){
            return resqData;
        }
        String pid = fromName+"_"+pageName;
        List<Map> list = (List) IusPluginUtil.getInstance().select("plateform","select * from sys_export_conf where p_id='"+pid+"' order by order_no,create_time",0,0);
        if(!StrUtil.isEmpty(list)){
            List<Map> result = new ArrayList();
            int size = list.size();
            for(int i=0; i<size; i++){
                Map<String,String> map = list.get(i);
                Map<String,Object> data = new HashMap();
                if("3".equals(map.get("attrType"))){//动态数据字典
                    JSONObject obj = JSON.parseObject(map.get("dictCof"));
                    List dictList = getDictList("",obj);
                    Map dictMap = getDicts(dictList,obj.getString("val"),obj.getString("text"));
                    data.put("data_dict",dictMap);
                    dictList = null;
                } else if("2".equals(map.get("attrType"))){//固定数据字典
                    JSONObject obj = JSON.parseObject(map.get("dictCof"));
                    List dictList = getDictList(obj.getString("dict"), obj);
                    Map dictMap = getDicts(dictList,"itemValue","itemText");
                    data.put("data_dict",dictMap);
                    dictList = null;
                }
                map.put("table_name", StringUtil.toCamelNamed(map.get("tableName")));
                data.put("attrName",map);
                String title =  map.get("attrTitle");//默认取中文
                switch (map.get("expTitleType")){
                    case "EN":
                        title= map.get("attrName");
                        break;
                    case "FD":
                        title= map.get("attrField");
                        break;
                }
                data.put("title","T".equals(map.get("ifTitleCap")) ? title.toUpperCase() : title.toLowerCase());
                result.add(data);
            }
            list = null;
            resqData.put("data_titles",result);
        }
        return resqData;
    }

    /**
     * 将数据字典转成map
     */
    private Map<String,String> getDicts(List<Map> data,String key,String valName){
        Map dictMap = new HashMap();
        int size = data.size();
        for (int i=0; i<size; i++) {
            Map<String,String> map = data.get(i);
            dictMap.put(map.get(key),map.get(valName));
        }
        return dictMap;
    }

    /**
     * 获取数据字典列表
     */
    private List getDictList(String enameCode, JSONObject obj){
        String sql = null;
        String datasource = "plateform";
        if(StrUtil.isNotNull(enameCode)){
            sql = "select item_value,item_text from dict_data_item where cate_ename='"+enameCode+"'";
        } else {
//            String key = obj.getString("formName") + "_" + obj.getString("pageName");
//            Map<String, Object> resultMap = new HashMap();
            Map map = (Map) CacheHelper.getInstance().getIusParamCache(obj.getString("formName") + "_" + obj.getString("pageName"));
            String objName = String.valueOf(map.get("modelTypes")).substring(2);
            String tableName = StringUtil.upperCharToUnderLine(objName);
            String colum = StringUtil.upperCharToUnderLine(obj.getString("val"))+","+StringUtil.upperCharToUnderLine(obj.getString("text"));
            datasource = String.valueOf(map.get("sysName"));
            sql = "select "+colum+" from "+tableName;
           /* Map params = IUSRequestParams.analyzeParams(map, resultMap);
            String resultColum = objName+"."+obj.getString("val")+","+objName+"."+obj.getString("text");
            params.put("result_column", resultColum);
            params.put("_resultType", "F");
            ParamsVo vo = new ParamsVo();
            vo.setParams(params);
            String sql = IusSqlTools.getInstance().selectNativeSql(vo);
            String datasource = String.valueOf(params.get("datasource"));
            return (List)IusPluginUtil.getInstance().select(datasource,sql,0,0);*/
        }
        log.info("dict sql->"+sql);
        return (List)IusPluginUtil.getInstance().select(datasource, sql,0,0);
    }
}
